package org.tool.core.lang.convert;

import org.tool.core.lang.convert.converter.Object2JsonStringConverter;
import org.tool.reflect.GenericUtil;

import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 对象转换工具类
 *
 * @author 李坤
 * @date 2022/7/10 16:24
 */
public abstract class ConvertUtil {

    /**
     * 类型转换器容器
     */
    private static final Map<Class, Converter> CONVERTER_MAPPING = new ConcurrentHashMap<>();

    // 注册内置的类型转换器
    static {
        register(new Object2JsonStringConverter());
    }

    /**
     * 将给定的对象转换为指定类型的对象
     *
     * @param source      原始对象
     * @param targetClass 目标类型
     * @param <T>         目标类型
     *
     * @return 目标类型的对象
     */
    public static <T> T convert(Object source, Class<T> targetClass) throws Exception {
        return (T) CONVERTER_MAPPING.get(targetClass).convert(source);
    }

    /**
     * 将给定的对象转换为指定类型的对象
     * <p>
     * 如果转换时出现异常，则返回默认值 {@code defaultValue}
     *
     * @param source       原始对象
     * @param targetClass  目标类型
     * @param <T>          目标类型
     * @param defaultValue 默认值
     *
     * @return 目标类型的对象
     */
    public static <T> T convertIgnoreException(Object source, Class<T> targetClass, T defaultValue) {
        if (Objects.nonNull(source) && Objects.nonNull(targetClass)) {
            Converter converter;
            if (Objects.nonNull(converter = CONVERTER_MAPPING.get(targetClass))) {
                try {
                    return (T) converter.convert(source);
                } catch (Exception ignored) {
                    return defaultValue;
                }
            }
        }
        return defaultValue;
    }

    /**
     * 向容器中注册给定的转换器
     *
     * @param converters 待注册的转换器
     */
    public static void register(Converter... converters) {
        Arrays.stream(converters).forEach(converter ->
                CONVERTER_MAPPING.put(GenericUtil.getSuperClassGenericType(converter), converter));
    }

}
